"""
用户信息Services层
负责用户相关业务逻辑处理，对外提供统一接口
"""
from typing import Optional, Dict, Any
from datetime import date, datetime
from werkzeug.security import check_password_hash, generate_password_hash
from app.Dao.AdminDao.UserDao.UserDao import UserDAO  # 导入DAO层
from app.Models.AdminModels.UserModels.UserModel import User  # 导入User模型


class UserServices:
    """用户信息业务逻辑层"""

    @staticmethod
    def register_user(
            username: str,
            email: str,
            password: str,
            birthday: Optional[date] = None,
            reg_time: Optional[datetime] = None
    ) -> tuple[bool, str]:
        """
        用户注册业务（密码哈希封装优化）
        :param username: 用户名（3-20位）
        :param email: 绑定邮箱
        :param password: 原始密码（6-16位，含字母和数字）
        :param birthday: 生日（可选）
        :param reg_time: 注册时间（可选）
        :return: (成功标识, 提示信息)
        """
        print(password)

        # 3. 调用DAO层添加用户（传递加密后的密码，而非原始密码）
        user = UserDAO.add_user(
            username=username,
            email=email,
            password=password,  # 传入哈希后的密码
            birthday=birthday,
            reg_time=reg_time or datetime.now()
        )

        if user:
            return True, f"注册成功！用户名：{username}，用户ID：{user.id}"
        else:
            return False, f"注册失败！用户名或邮箱已被占用，或系统异常"

    @staticmethod
    def user_login(username: str, password: str):
        """
        用户登录业务
        :param username: 用户名
        :param password: 原始密码
        :return: (成功标识, 提示信息, 用户实例/None)
        """
        # 1. 调用DAO层查询用户
        user = UserDAO.get_user_by_username(username)
        if not user:
            return False, f"登录失败！用户名不存在"

        # 2. 密码校验
        if check_password_hash(user.password, password):
            return True, {"user_id": user.id, "msg": "登录成功"}
        else:
            print(user.password, password)
            return False, f"登录失败！密码错误"

    @staticmethod
    def get_user_by_id(user_id: int) -> tuple[bool, str, Optional[Dict[str, Any]]]:
        """
        根据ID查询用户详情
        :param user_id: 用户ID
        :return: (成功标识, 提示信息, 用户信息字典/None)
        """
        user = UserDAO.get_user_by_id(user_id)
        if user:
            return True, f"查询成功", user.to_dict()
        else:
            return False, f"查询失败！用户ID：{user_id} 不存在", None

    @staticmethod
    def get_user_by_username(username: str) -> tuple[bool, str, Optional[Dict[str, Any]]]:
        """
        根据用户名查询用户详情
        :param username: 用户名
        :return: (成功标识, 提示信息, 用户信息字典/None)
        """
        user = UserDAO.get_user_by_username(username)
        if user:
            return True, f"查询成功", user.to_dict()
        else:
            return False, f"查询失败！用户名：{username} 不存在", None

    @staticmethod
    def get_user_by_email(email: str) -> tuple[bool, str, Optional[Dict[str, Any]]]:
        """
        根据邮箱查询用户详情（用于忘记密码）
        :param email: 绑定邮箱
        :return: (成功标识, 提示信息, 用户信息字典/None)
        """
        user = UserDAO.get_user_by_email(email)
        if user:
            return True, f"查询成功", user.to_dict()
        else:
            return False, f"查询失败！邮箱：{email} 未绑定任何账号", None

    @staticmethod
    def get_all_users(page: int = 1, per_page: int = 20) -> tuple[bool, str, Dict[str, Any]]:
        """
        分页查询所有用户（管理员业务）
        :param page: 页码
        :param per_page: 每页条数
        :return: (成功标识, 提示信息, 分页数据字典)
        """
        user_page = UserDAO.get_all_users(page=page, per_page=per_page)
        if user_page["total"] > 0:
            return True, f"查询成功！共{user_page['total']}条用户数据", user_page
        else:
            return False, f"查询成功！暂无用户数据", user_page

    @staticmethod
    def update_user_info(
            user_id: int,
            **kwargs
    ) -> tuple[bool, str, Optional[Dict[str, Any]]]:
        """
        更新用户信息业务
        :param user_id: 用户ID
        :param kwargs: 要更新的字段（username/email/password/birthday）
        :return: (成功标识, 提示信息, 更新后用户字典/None)
        """
        # 1. 校验更新字段合法性（简单过滤）
        allowed_fields = ['username', 'email', 'password', 'birthday']
        update_kwargs = {k: v for k, v in kwargs.items() if k in allowed_fields and v is not None}
        if not update_kwargs:
            return False, f"更新失败！未提供有效更新字段", None

        # 2. 密码更新时的格式校验
        if 'password' in update_kwargs:
            password = update_kwargs['password']
            if len(password) < 6 or len(password) > 16:
                return False, f"更新失败！密码需6-16位字符", None
            if not (any(char.isalpha() for char in password) and any(char.isdigit() for char in password)):
                return False, f"更新失败！密码需同时包含字母和数字", None

        # 3. 调用DAO层执行更新
        updated_user = UserDAO.update_user(user_id=user_id, **update_kwargs)
        if updated_user:
            return True, f"更新成功！用户ID：{user_id}", updated_user.to_dict()
        else:
            return False, f"更新失败！用户不存在或更新字段已被占用", None

    @staticmethod
    def delete_user(user_id: int) -> tuple[bool, str]:
        """
        删除用户业务（管理员业务）
        :param user_id: 用户ID
        :return: (成功标识, 提示信息)
        """
        # 1. 先查询用户是否存在（避免DAO层重复查询，可选）
        exist, _, _ = UserServices.get_user_by_id(user_id)
        if not exist:
            return False, f"删除失败！用户ID：{user_id} 不存在"

        # 2. 调用DAO层执行删除
        delete_success = UserDAO.delete_user(user_id=user_id)
        if delete_success:
            return True, f"删除成功！用户ID：{user_id} 已删除"
        else:
            return False, f"删除失败！系统异常，请稍后重试"

    @staticmethod
    def check_user_exist(username: Optional[str] = None, email: Optional[str] = None) -> tuple[bool, str]:
        """
        检查用户名/邮箱是否已存在（注册表单校验）
        :param username: 用户名（可选）
        :param email: 邮箱（可选）
        :return: (存在标识, 提示信息)
        """
        if not username and not email:
            return False, f"校验失败！未提供用户名或邮箱"

        exist = UserDAO.check_user_exist(username=username, email=email)
        if username and exist:
            return True, f"用户名'{username}'已被占用"
        return False, f"校验通过！用户名/邮箱可使用"
